#include "bsp.h"

#if HardwareType == Common_Hardware_Type
CAN_HandleTypeDef CAN1Handle;
CAN_HandleTypeDef CAN2Handle;

__weak void BSP_CAN1_FIFO0_Callback(P_CAN_RX pcanrx)
{
    return;
}

__weak void BSP_CAN1_FIFO1_Callback(P_CAN_RX pcanrx)
{
    return;
}

__weak void BSP_CAN2_FIFO0_Callback(P_CAN_RX pcanrx)
{
    return;
}
__weak void BSP_CAN2_FIFO1_Callback(P_CAN_RX pcanrx)
{
    return;
}

void HAL_CAN_RxFifo0MsgPendingCallback (CAN_HandleTypeDef *hcan)
{
    static CAN_RX can1_f0 = {0};
    static CAN_RX can2_f0 = {0};

    if(hcan->Instance == CAN1)
    {
        HAL_CAN_GetRxMessage(&CAN1Handle, CAN_RX_FIFO0, &can1_f0.hdr, can1_f0.data);
        BSP_CAN1_FIFO0_Callback(&can1_f0);
    }
    else if(hcan->Instance == CAN2)
    {
        HAL_CAN_GetRxMessage(&CAN2Handle, CAN_RX_FIFO0, &can2_f0.hdr, can2_f0.data);
        BSP_CAN2_FIFO0_Callback(&can2_f0);
    }
}

void HAL_CAN_RxFifo1MsgPendingCallback (CAN_HandleTypeDef *hcan)
{
    static CAN_RX can1_f1 = {0};
    static CAN_RX can2_f1 = {0};

    if(hcan->Instance == CAN1)
    {
        HAL_CAN_GetRxMessage(&CAN1Handle, CAN_RX_FIFO1, &can1_f1.hdr, can1_f1.data);
        BSP_CAN1_FIFO1_Callback(&can1_f1);
    }
    else if(hcan->Instance == CAN2)
    {
        HAL_CAN_GetRxMessage(&CAN2Handle, CAN_RX_FIFO1, &can2_f1.hdr, can2_f1.data);
        BSP_CAN2_FIFO1_Callback(&can2_f1);
    }
}


void CAN_FilterInit(CAN_TypeDef *CANx, FilterUnit unit[], uint16_t num)
{
    CAN_FilterTypeDef FilterConfig = {0};

    if(num > 14)
    {
        num = 14;
    }

    if(num == 0)    //所有ID均压入FIFO0
    {
        FilterConfig.SlaveStartFilterBank   = 14;                       //过滤器组：CAN1 0-13，CAN2 14-27
        FilterConfig.FilterBank             = CANx == CAN1 ? 0 : 14;    //CAN1用过滤器组0，CAN2用过滤器组14
        FilterConfig.FilterMode             = CAN_FILTERMODE_IDMASK;    //掩码模式
        FilterConfig.FilterScale            = CAN_FILTERSCALE_32BIT;    //32位模式

        FilterConfig.FilterIdHigh           = 0x0000;
        FilterConfig.FilterIdLow            = 0x0000;
        FilterConfig.FilterMaskIdHigh       = 0x0000;
        FilterConfig.FilterMaskIdLow        = 0x0000;
        FilterConfig.FilterFIFOAssignment   = CAN_RX_FIFO0;             //数据压入FIFO0
        FilterConfig.FilterActivation       = ENABLE;                   //过滤器使能

        HAL_CAN_ConfigFilter(&CAN1Handle, &FilterConfig);
    }
    else
    {
        uint16_t i = 0;

        for(i = 0; i <= num - 1; i++)
        {
            FilterConfig.SlaveStartFilterBank   = 14;                     
            FilterConfig.FilterBank             = CANx == CAN1 ? i : i + 14;
            FilterConfig.FilterFIFOAssignment   = unit[i].FilterFIFO;
            FilterConfig.FilterActivation       = ENABLE;                   //过滤器使能

            switch (unit[i].mode)
            {
                case MODE_MASK32:
                    FilterConfig.FilterMode     = CAN_FILTERMODE_IDMASK;
                    FilterConfig.FilterScale    = CAN_FILTERSCALE_32BIT;
                    break;
                case MODE_LIST32:
                    FilterConfig.FilterMode     = CAN_FILTERMODE_IDLIST;
                    FilterConfig.FilterScale    = CAN_FILTERSCALE_32BIT;
                    break;
                case MODE_MASK16:
                    FilterConfig.FilterMode     = CAN_FILTERMODE_IDMASK;
                    FilterConfig.FilterScale    = CAN_FILTERSCALE_16BIT; 
                    break;
                case MODE_LIST16:
                    FilterConfig.FilterMode     = CAN_FILTERMODE_IDLIST;
                    FilterConfig.FilterScale    = CAN_FILTERSCALE_16BIT;
                break;
            
            }

            FilterConfig.FilterIdLow        = unit[i].reg.hal.FilterIdLow;
            FilterConfig.FilterIdHigh       = unit[i].reg.hal.FilterIdHigh;
            FilterConfig.FilterMaskIdLow    = unit[i].reg.hal.FilterMaskIdLow;
            FilterConfig.FilterMaskIdHigh   = unit[i].reg.hal.FilterMaskIdHigh;

            HAL_CAN_ConfigFilter(&CAN1Handle, &FilterConfig);
        }
    }
}

void CAN_Init(CAN_TypeDef *CANx, FilterUnit unit[], uint16_t num)
{   
    CAN_HandleTypeDef *phandle;
    if(CANx == CAN1)
    {
        phandle = &CAN1Handle;
    }
    else
    {
        phandle = &CAN2Handle;
    }
    phandle->Instance                     = CANx;
    phandle->Init.Prescaler               = 3;                //APB1总线时钟为42MHz，3分频后为14MHz
    phandle->Init.Mode                    = CAN_MODE_NORMAL;
    phandle->Init.SyncJumpWidth           = CAN_SJW_4TQ;
    phandle->Init.TimeSeg1                = CAN_BS1_7TQ;
    phandle->Init.TimeSeg2                = CAN_BS2_6TQ;      //CAN波特率为 14MHz / (7 + 6 + 1) = 1MHz
    phandle->Init.TimeTriggeredMode       = DISABLE;          //0：禁止时间触发通信模式
    phandle->Init.AutoBusOff              = DISABLE;          //0：软件自动离线管理   控制can硬件在退出总线关闭状态下的行为
    phandle->Init.AutoWakeUp              = DISABLE;          //0：sleep位清零后，退出睡眠模式      1：一旦检测到can消息时，通过硬件退出睡眠模式
    phandle->Init.AutoRetransmission      = ENABLE;           //0：报文自动传送，直到can消息发送成功 1：无论发送结果如何，均只发送一次
    phandle->Init.ReceiveFifoLocked       = DISABLE;          //0：fifo上溢后报文不锁定,新的覆盖旧的 1：fifo上溢后报文锁定,新的消息将被丢弃
    phandle->Init.TransmitFifoPriority    = DISABLE;          //0：优先级由报文标识符决定            1：优先级由请求顺序（时间顺序）确定
    
    HAL_CAN_Init(phandle);
    CAN_FilterInit(CANx, unit, num);

    HAL_CAN_ActivateNotification(phandle,   CAN_IT_RX_FIFO0_MSG_PENDING
                                        |   CAN_IT_RX_FIFO1_MSG_PENDING     );
    HAL_CAN_Start(phandle);         
}

void HAL_CAN_MspInit(CAN_HandleTypeDef* hcan)
{
    GPIO_InitTypeDef GPIO_InitStruct;

    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;

    if(hcan->Instance == CAN1)
    {
        __HAL_RCC_CAN1_CLK_ENABLE();

        CAN1_TX_PORT_CLK_ENABLE();
        CAN1_RX_PORT_CLK_ENABLE();

        GPIO_InitStruct.Alternate =  GPIO_AF9_CAN1;
        GPIO_InitStruct.Pin = CAN1_TX_PIN;
        HAL_GPIO_Init(CAN1_TX_PORT, &GPIO_InitStruct);

        GPIO_InitStruct.Alternate =  GPIO_AF9_CAN1;
        GPIO_InitStruct.Pin = CAN1_RX_PIN;
        HAL_GPIO_Init(CAN1_RX_PORT, &GPIO_InitStruct);   

        HAL_NVIC_SetPriority(CAN1_RX0_IRQn, 1, 0);
        HAL_NVIC_SetPriority(CAN1_RX1_IRQn, 1, 0);
        HAL_NVIC_EnableIRQ(CAN1_RX0_IRQn);
        HAL_NVIC_EnableIRQ(CAN1_RX1_IRQn);        
    }
    else if(hcan->Instance == CAN2)
    {
        __HAL_RCC_CAN2_CLK_ENABLE();

        CAN2_TX_PORT_CLK_ENABLE();
        CAN2_RX_PORT_CLK_ENABLE();

        GPIO_InitStruct.Alternate =  GPIO_AF9_CAN2;
        GPIO_InitStruct.Pin = CAN2_TX_PIN;
        HAL_GPIO_Init(CAN2_TX_PORT, &GPIO_InitStruct);

        GPIO_InitStruct.Alternate =  GPIO_AF9_CAN2;
        GPIO_InitStruct.Pin = CAN2_RX_PIN;
        HAL_GPIO_Init(CAN2_RX_PORT, &GPIO_InitStruct);           

        HAL_NVIC_SetPriority(CAN2_RX0_IRQn, 2, 0);
        HAL_NVIC_SetPriority(CAN2_RX1_IRQn, 2, 0);
        HAL_NVIC_EnableIRQ(CAN2_RX0_IRQn);
        HAL_NVIC_EnableIRQ(CAN2_RX1_IRQn);
    }
}

void HAL_CAN_MspDeInit(CAN_HandleTypeDef *hcan)
{
    if(hcan->Instance==CAN1)
    {
        __HAL_RCC_CAN1_FORCE_RESET();
        __HAL_RCC_CAN1_RELEASE_RESET();
        HAL_GPIO_DeInit(CAN1_TX_PORT, CAN1_TX_PIN);
        HAL_GPIO_DeInit(CAN1_RX_PORT, CAN1_RX_PIN);        
    }
    else if(hcan->Instance == CAN2)
    {
        __HAL_RCC_CAN2_FORCE_RESET();
        __HAL_RCC_CAN2_RELEASE_RESET();
        HAL_GPIO_DeInit(CAN2_TX_PORT, CAN2_TX_PIN);
        HAL_GPIO_DeInit(CAN2_RX_PORT, CAN2_RX_PIN);        
    }
}



#elif HardwareType == Engineer_Hardware_Type

CAN_HandleTypeDef CAN1Handle;
CAN_HandleTypeDef CAN2Handle;

__weak void BSP_CAN1_FIFO0_Callback(P_CAN_RX pcanrx)
{
    return;
}

__weak void BSP_CAN1_FIFO1_Callback(P_CAN_RX pcanrx)
{
    return;
}

__weak void BSP_CAN2_FIFO0_Callback(P_CAN_RX pcanrx)
{
    return;
}
__weak void BSP_CAN2_FIFO1_Callback(P_CAN_RX pcanrx)
{
    return;
}

void HAL_CAN_RxFifo0MsgPendingCallback (CAN_HandleTypeDef *hcan)
{
    static CAN_RX can1_f0 = {0};
    static CAN_RX can2_f0 = {0};

    if(hcan->Instance == CAN1)
    {
        HAL_CAN_GetRxMessage(&CAN1Handle, CAN_RX_FIFO0, &can1_f0.hdr, can1_f0.data);
        BSP_CAN1_FIFO0_Callback(&can1_f0);
    }
    else if(hcan->Instance == CAN2)
    {
        HAL_CAN_GetRxMessage(&CAN2Handle, CAN_RX_FIFO0, &can2_f0.hdr, can2_f0.data);
        BSP_CAN2_FIFO0_Callback(&can2_f0);
    }
}

void HAL_CAN_RxFifo1MsgPendingCallback (CAN_HandleTypeDef *hcan)
{
    static CAN_RX can1_f1 = {0};
    static CAN_RX can2_f1 = {0};

    if(hcan->Instance == CAN1)
    {
        HAL_CAN_GetRxMessage(&CAN1Handle, CAN_RX_FIFO1, &can1_f1.hdr, can1_f1.data);
        BSP_CAN1_FIFO1_Callback(&can1_f1);
    }
    else if(hcan->Instance == CAN2)
    {
        HAL_CAN_GetRxMessage(&CAN2Handle, CAN_RX_FIFO1, &can2_f1.hdr, can2_f1.data);
        BSP_CAN2_FIFO1_Callback(&can2_f1);
    }
}


void CAN_FilterInit(CAN_TypeDef *CANx, FilterUnit unit[], uint16_t num)
{
    CAN_FilterTypeDef FilterConfig = {0};

    if(num > 14)
    {
        num = 14;
    }

    if(num == 0)    //所有ID均压入FIFO0
    {
        FilterConfig.SlaveStartFilterBank   = 14;                       //过滤器组：CAN1 0-13，CAN2 14-27
        FilterConfig.FilterBank             = CANx == CAN1 ? 0 : 14;    //CAN1用过滤器组0，CAN2用过滤器组14
        FilterConfig.FilterMode             = CAN_FILTERMODE_IDMASK;    //掩码模式
        FilterConfig.FilterScale            = CAN_FILTERSCALE_32BIT;    //32位模式

        FilterConfig.FilterIdHigh           = 0x0000;
        FilterConfig.FilterIdLow            = 0x0000;
        FilterConfig.FilterMaskIdHigh       = 0x0000;
        FilterConfig.FilterMaskIdLow        = 0x0000;
        FilterConfig.FilterFIFOAssignment   = CAN_RX_FIFO0;             //数据压入FIFO0
        FilterConfig.FilterActivation       = ENABLE;                   //过滤器使能

        HAL_CAN_ConfigFilter(&CAN1Handle, &FilterConfig);
    }
    else
    {
        uint16_t i = 0;

        for(i = 0; i <= num - 1; i++)
        {
            FilterConfig.SlaveStartFilterBank   = 14;                     
            FilterConfig.FilterBank             = CANx == CAN1 ? i : i + 14;
            FilterConfig.FilterFIFOAssignment   = unit[i].FilterFIFO;
            FilterConfig.FilterActivation       = ENABLE;                   //过滤器使能

            switch (unit[i].mode)
            {
                case MODE_MASK32:
                    FilterConfig.FilterMode     = CAN_FILTERMODE_IDMASK;
                    FilterConfig.FilterScale    = CAN_FILTERSCALE_32BIT;
                    break;
                case MODE_LIST32:
                    FilterConfig.FilterMode     = CAN_FILTERMODE_IDLIST;
                    FilterConfig.FilterScale    = CAN_FILTERSCALE_32BIT;
                    break;
                case MODE_MASK16:
                    FilterConfig.FilterMode     = CAN_FILTERMODE_IDMASK;
                    FilterConfig.FilterScale    = CAN_FILTERSCALE_16BIT; 
                    break;
                case MODE_LIST16:
                    FilterConfig.FilterMode     = CAN_FILTERMODE_IDLIST;
                    FilterConfig.FilterScale    = CAN_FILTERSCALE_16BIT;
                break;
            
            }

            FilterConfig.FilterIdLow        = unit[i].reg.hal.FilterIdLow;
            FilterConfig.FilterIdHigh       = unit[i].reg.hal.FilterIdHigh;
            FilterConfig.FilterMaskIdLow    = unit[i].reg.hal.FilterMaskIdLow;
            FilterConfig.FilterMaskIdHigh   = unit[i].reg.hal.FilterMaskIdHigh;

            HAL_CAN_ConfigFilter(&CAN1Handle, &FilterConfig);
        }
    }
}

void CAN_Init(CAN_TypeDef *CANx, FilterUnit unit[], uint16_t num)
{   
    CAN_HandleTypeDef *phandle;
    if(CANx == CAN1)
    {
        phandle = &CAN1Handle;
    }
    else
    {
        phandle = &CAN2Handle;
    }
    phandle->Instance                     = CANx;
    phandle->Init.Prescaler               = 3;                //APB1总线时钟为42MHz，3分频后为14MHz
    phandle->Init.Mode                    = CAN_MODE_NORMAL;
    phandle->Init.SyncJumpWidth           = CAN_SJW_4TQ;
    phandle->Init.TimeSeg1                = CAN_BS1_7TQ;
    phandle->Init.TimeSeg2                = CAN_BS2_6TQ;      //CAN波特率为 14MHz / (7 + 6 + 1) = 1MHz
    phandle->Init.TimeTriggeredMode       = DISABLE;
    phandle->Init.AutoBusOff              = DISABLE;
    phandle->Init.AutoWakeUp              = DISABLE;
    phandle->Init.AutoRetransmission      = DISABLE;
    phandle->Init.ReceiveFifoLocked       = DISABLE;
    phandle->Init.TransmitFifoPriority    = DISABLE;
    
    HAL_CAN_Init(phandle);
    CAN_FilterInit(CANx, unit, num);


    HAL_CAN_ActivateNotification(phandle,   CAN_IT_RX_FIFO0_MSG_PENDING
                                        |   CAN_IT_RX_FIFO1_MSG_PENDING     );
    HAL_CAN_Start(phandle);         
}



void HAL_CAN_MspInit(CAN_HandleTypeDef* hcan)
{
    GPIO_InitTypeDef GPIO_InitStruct;

    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;

    if(hcan->Instance == CAN1)
    {
        __HAL_RCC_CAN1_CLK_ENABLE();

        CAN1_TX_PORT_CLK_ENABLE();
        CAN1_RX_PORT_CLK_ENABLE();

        GPIO_InitStruct.Alternate =  GPIO_AF9_CAN1;
        GPIO_InitStruct.Pin = CAN1_TX_PIN;
        HAL_GPIO_Init(CAN1_TX_PORT, &GPIO_InitStruct);

        GPIO_InitStruct.Alternate =  GPIO_AF9_CAN1;
        GPIO_InitStruct.Pin = CAN1_RX_PIN;
        HAL_GPIO_Init(CAN1_RX_PORT, &GPIO_InitStruct);   

        HAL_NVIC_SetPriority(CAN1_RX0_IRQn, 1, 0);
        HAL_NVIC_SetPriority(CAN1_RX1_IRQn, 1, 0);
        HAL_NVIC_EnableIRQ(CAN1_RX0_IRQn);
        HAL_NVIC_EnableIRQ(CAN1_RX1_IRQn);        
    }
    else if(hcan->Instance == CAN2)
    {
        __HAL_RCC_CAN2_CLK_ENABLE();

        CAN2_TX_PORT_CLK_ENABLE();
        CAN2_RX_PORT_CLK_ENABLE();

        GPIO_InitStruct.Alternate =  GPIO_AF9_CAN2;
        GPIO_InitStruct.Pin = CAN2_TX_PIN;
        HAL_GPIO_Init(CAN2_TX_PORT, &GPIO_InitStruct);

        GPIO_InitStruct.Alternate =  GPIO_AF9_CAN2;
        GPIO_InitStruct.Pin = CAN2_RX_PIN;
        HAL_GPIO_Init(CAN2_RX_PORT, &GPIO_InitStruct);           

        HAL_NVIC_SetPriority(CAN2_RX0_IRQn, 1, 0);
        HAL_NVIC_SetPriority(CAN2_RX1_IRQn, 1, 0);
        HAL_NVIC_EnableIRQ(CAN2_RX0_IRQn);
        HAL_NVIC_EnableIRQ(CAN2_RX1_IRQn);
    }
}

void HAL_CAN_MspDeInit(CAN_HandleTypeDef *hcan)
{
    if(hcan->Instance==CAN1)
    {
        __HAL_RCC_CAN1_FORCE_RESET();
        __HAL_RCC_CAN1_RELEASE_RESET();
        HAL_GPIO_DeInit(CAN1_TX_PORT, CAN1_TX_PIN);
        HAL_GPIO_DeInit(CAN1_RX_PORT, CAN1_RX_PIN);        
    }
    else if(hcan->Instance == CAN2)
    {
        __HAL_RCC_CAN2_FORCE_RESET();
        __HAL_RCC_CAN2_RELEASE_RESET();
        HAL_GPIO_DeInit(CAN2_TX_PORT, CAN2_TX_PIN);
        HAL_GPIO_DeInit(CAN2_RX_PORT, CAN2_RX_PIN);        
    }
}

#endif

